home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Video
/
World of Video.iso
/
gfxprograms
/
viewers
/
viewtek
/
anim7.doc
next >
Wrap
Text File
|
1995-02-13
|
29KB
|
602 lines
A N I M
An IFF Format For CEL Animations
Revision date: 4 May 1988
prepared by:
SPARTA Inc.
23041 de la Carlota
Laguna Hills, Calif 92653
(714) 768-8161
contact: Gary Bonham
also by:
Aegis Development Co.
2115 Pico Blvd.
Santa Monica, Calif 90405
213) 392-9972
Anim7 Appendix (july 92) by:
Wolfgang Hofer
A-2722 Winzendorf
Wr. Neustaedterstr. 140
1.0 Introduction
The ANIM IFF format was developed at Sparta originally for the
production of animated video sequences on the Amiga computer. The
intent was to be able to store, and play back, sequences of frames
and to minimize both the storage space on disk (through compression)
and playback time (through efficient de-compression algorithms).
It was desired to maintain maximum compatibility with existing
IFF formats and to be able to display the initial frame as a normal
still IFF picture.
Several compression schemes have been introduced in the ANIM format.
Most of these are strictly of historical interest as the only one
currently being placed in new code is the vertical run length
encoded byte encoding developed by Jim Kent.
1.1 ANIM Format Overview
The general philosophy of ANIMs is to present the initial frame
as a normal, run-length-encoded, IFF picture. Subsequent
frames are then described by listing only their differences
from a previous frame. Normally, the "previous" frame is two
frames back as that is the frame remaining in the hidden
screen buffer when double-buffering is used. To better
understand this, suppose one has two screens, called A and B,
and the ability to instantly switch the display from one to
the other. The normal playback mode is to load the initial
frame into A and duplicate it into B. Then frame A is displayed
on the screen. Then the differences for frame 2 are used to
alter screen B and it is displayed. Then the differences for
frame 3 are used to alter screen A and it is displayed, and so
on. Note that frame 2 is stored as differences from frame 1,
but all other frames are stored as differences from two frames
back.
ANIM is an IFF FORM and its basic format is as follows (this
assumes the reader has a basic understanding of IFF format
files):
FORM ANIM
. FORM ILBM first frame
. . BMHD normal type IFF data
. . ANHD optional animation header
chunk for timing of 1st frame.
. . CMAP
. . BODY
. FORM ILBM frame 2
. . ANHD animation header chunk
. . DLTA delta mode data
. FORM ILBM frame 3
. . ANHD
. . DLTA
...
The initial FORM ILBM can contain all the normal ILBM chunks,
such as CRNG, etc. The BODY will normally be a standard
run-length-encoded data chunk (but may be any other legal
compression mode as indicated by the BMHD). If desired, an ANHD
chunk can appear here to provide timing data for the first
frame. If it is here, the operation field should be =0.
The subsequent FORMs ILBM contain an ANHD, instead of a BMHD,
which duplicates some of BMHD and has additional parameters
pertaining to the animation frame. The DLTA chunk contains
the data for the delta compression modes. If
the older XOR compression mode is used, then a BODY chunk
will be here. In addition, other chunks may be placed in each
of these as deemed necessary (and as code is placed in player
programs to utilize them). A good example would be CMAP chunks
to alter the color palette. A basic assumption in ANIMs is
that the size of the bitmap, and the display mode (e.g. HAM)
will not change through the animation. Take care when playing
an ANIM that if a CMAP occurs with a frame, then the change must
be applied to both buffers.
Note that the DLTA chunks are not interleaved bitmap representations,
thus the use of the ILBM form is inappropriate for these frames.
However, this inconsistency was not noted until there were a number
of commercial products either released or close to release which
generated/played this format. Therefore, this is probably an
inconsistency which will have to stay with us.
1.2 Recording ANIMs
To record an ANIM will require three bitmaps - one for
creation of the next frame, and two more for a "history" of the
previous two frames for performing the compression calculations
(e.g. the delta mode calculations).
There are five frame-to-frame compression methods currently
defined. The first three are mainly for historical interest.
The product Aegis VideoScape 3D utilizes the third method in
version 1.0, but switched to method 5 on 2.0. This is
the only instance known of a commercial product generating
ANIMs of any of the first three methods. The fourth method
is a general short or long word compression scheme which has
several options including whether the compression is horizontal
or vertical, and whether or not it is XOR format. This offers
a choice to the user for the optimization of file size and/or
playback speed. The fifth method is the byte vertical run length
encoding as designed by Jim Kent. Do not confuse
this with Jim's RIFF file format which is different than ANIM.
Here we utilized his compression/decompression routines within the
ANIM file structure.
The following paragraphs give a general outline of each of the
methods of compression currently included in this spec.
1.2.1 XOR mode
This mode is the original and is included here for historical
interest. In general, the delta modes are far superior.
The creation of XOR mode is quite simple. One simply
performs an exclusive-or (XOR) between all corresponding
bytes of the new frame and two frames back. This results
in a new bitmap with 0 bits wherever the two frames were
identical, and 1 bits where they are different. Then this
new bitmap is saved using run-length-encoding. A major
obstacle of this mode is in the time consumed in performing
the XOR upon reconstructing the image.
1.2.2 Long Delta mode
This mode stores the actual new frame long-words which are
different, along with the offset in the bitmap. The
exact format is shown and discussed in section 2 below.
Each plane is handled separately, with no data being saved
if no changes take place in a given plane. Strings of
2 or more long-words in a row which change can be run
together so offsets do not have to be saved for each one.
Constructing this data chunk usually consists of having
a buffer to hold the data, and calculating the data as
one compares the new frame, long-word by long-word, with
two frames back.
1.2.3 Short Delta mode
This mode is identical to the Long Delta mode except that
short-words are saved instead of long-words. In most
instances, this mode results in a smaller DLTA chunk.
The Long Delta mode is mainly of interest in improving
the playback speed when used on a 32-bit 68020 Turbo Amiga.
1.2.4 General Delta mode
The above two delta compression modes were hastily put together.
This mode was an attempt to provide a well-thought-out delta
compression scheme. Options provide for both short and long
word compression, either vertical or horizontal compression,
XOR mode (which permits reverse playback), etc. About the time
this was being finalized, the fifth mode, below, was developed
by Jim Kent. In practice the short-vertical-run-length-encoded
deltas in this mode play back faster than the fifth mode (which
is in essence a byte-vertical-run-length-encoded delta mode) but
does not compress as well - especially for very noisy data such
as digitized images. In most cases, playback speed not being
terrifically slower, the better compression (sometimes 2x) is
preferable due to limited storage media in most machines.
Details on this method are contained in section 2.2.2 below.
1.2.5 Byte Vertical Compression
This method does not offer the many options that method 4 offers,
but is very successful at producing decent compression even for
very noisy data such as digitized images. The method was devised
by Jim Kent and is utilized in his RIFF file format which is
different than the ANIM format. The description of this method
in this document is taken from Jim's writings. Further, he has
released both compression and decompression code to public domain.
Details on this method are contained in section 2.2.3 below.
1.3 Playing ANIMs
Playback of ANIMs will usually require two buffers, as mentioned
above, and double-buffering between them. The frame data from
the ANIM file is used to modify the hidden frame to the next
frame to be shown. When using the XOR mode, the usual run-
length-decoding routine can be easily modified to do the
exclusive-or operation required. Note that runs of zero bytes,
which will be very common, can be ignored, as an exclusive or
of any byte value to a byte of zero will not alter the original
byte value.
The general procedure, for all compression techniques, is to first
decode the initial ILBM picture into the hidden buffer and double-
buffer it into view. Then this picture is copied to the other (now
hidden) buffer. At this point each frame is displayed with the
same procedure. The next frame is formed in the hidden buffer by
applying the DLTA data (or the XOR data from the BODY chunk in the
case of the first XOR method) and the new frame is double-buffered
into view. This process continues to the end of the file.
A master colormap should be kept for the entire ANIM which would
be initially set from the CMAP chunk in the initial ILBM. This
colormap should be used for each frame. If a CMAP chunk appears
in one of the frames, then this master colormap is updated and the
new colormap applies to all frames until the occurrance of another
CMAP chunk.
Looping ANIMs may be constructed by simply making the last two frames
identical to the first two. Since the first two frames are special
cases (the first being a normal ILBM and the second being a delta from
the first) one can continually loop the anim by repeating from frame
three. In this case the delta for creating frame three will modify
the next to the last frame which is in the hidden buffer (which is
identical to the first frame), and the delta for creating frame four
will modify the last frame which is identical to the second frame.
Multi-File ANIMs are also supported so long as the first two frames
of a subsequent file are identical to the last two frames of the
preceeding file. Upon reading subsequent files, the ILBMs for the
first two frames are simply ignored, and the remaining frames are
simply appended to the preceeding frames. This permits splitting
ANIMs across multiple floppies and also permits playing each section
independently and/or editing it independent of the rest of the ANIM.
Timing of ANIM playback is easily achieved using the vertical blank
interrupt of the Amiga. There is an example of setting up such
a timer in the ROM Kernel Manual. Be sure to remember the timer
value when a frame is flipped up, so the next frame can be flipped
up relative to that time. This will make the playback independent
of how long it takes to decompress a frame (so long as there is enough
time between frames to accomplish this decompression).
2.0 Chunk Formats
2.1 ANHD Chunk
The ANHD chunk consists of the following data structure:
UBYTE operation The compression method:
=0 set directly (normal ILBM BODY),
=1 XOR ILBM mode,
=2 Long Delta mode,
=3 Short Delta mode,
=4 Generalized short/long Delta mode,
=5 Byte Vertical Delta mode
=7 short/long Vertical Delta mode
=74 (ascii 'J') reserved for Eric Graham's
compression technique (details to be
released later).
UBYTE mask (XOR mode only - plane mask where each
bit is set =1 if there is data and =0
if not.)
UWORD w,h (XOR mode only - width and height of the
area represented by the BODY to eliminate
unnecessary un-changed data)
WORD x,y (XOR mode only - position of rectangular
area representd by the BODY)
ULONG abstime (currently unused - timing for a frame
relative to the time the first frame
was displayed - in jiffies (1/60 sec))
ULONG reltime (timing for frame relative to time
previous frame was displayed - in
jiffies (1/60 sec))
UBYTE interleave (unused so far - indicates how may frames
back this data is to modify. =0 defaults
to indicate two frames back (for double
buffering). =n indicates n frames back.
The main intent here is to allow values
of =1 for special applications where
frame data would modify the immediately
previous frame)
UBYTE pad0 Pad byte, not used at present.
ULONG bits 32 option bits used by options=4 and 5.
At present only 6 are identified, but the
rest are set =0 so they can be used to
implement future ideas. These are defined
for option 4 only at this point. It is
recommended that all bits be set =0 for
option 5 and that any bit settings
used in the future (such as for XOR mode)
be compatible with the option 4
bit settings. Player code should check
undefined bits in options 4 and 5 to assure
they are zero.
The six bits for current use are:
bit # set =0 set =1
===============================================
0 short data long data
1 set XOR
2 separate info one info list
for each plane for all planes
3 not RLC RLC (run length coded)
4 horizontal vertical
5 short info offsets long info offsets
UBYTE pad[16] This is a pad for future use for future
compression modes.
2.2 DLTA Chunk
This chunk is the basic data chunk used to hold delta compression
data. The format of the data will be dependent upon the exact
compression format selected. At present there are two basic
formats for the overall structure of this chunk.
2.2.1 Format for methods 2 & 3
This chunk is a basic data chunk used to hold the delta
compression data. The minimum size of this chunk is 32 bytes
as the first 8 long-words are byte pointers into the chunk for
the data for each of up to 8 bitplanes. The pointer for the
plane data starting immediately following these 8 pointers will
have a value of 32 as the data starts in the 33-rd byte of the
chunk (index value of 32 due to zero-base indexing).
The data for a given plane consists of groups of data words. In
Long Delta mode, these groups consist of both short and long
words - short words for offsets and numbers, and long words for
the actual data. In Short Delta mode, the groups are identical
except data words are also shorts so all data is short words.
Each group consists of a starting word which is an offset. If
the offset is positive then it indicates the increment in long
or short words (whichever is appropriate) through the bitplane.
In other words, if you were reconstructing the plane, you would
start a pointer (to shorts or longs depending on the mode) to
point to the first word of the bitplane. Then the offset would
be added to it and the following data word would be placed at
that position. Then the next offset would be added to the
pointer and the following data word would be placed at that
position. And so on... The data terminates with an offset
equal to 0xFFFF.
A second interpretation is given if the offset is negative. In
that case, the absolute value is the offset+2. Then the
following short-word indicates the number of data words that
follow. Following that is the indicated number of contiguous
data words (longs or shorts depending on mode) which are to
be placed in contiguous locations of the bitplane.
If there are no changed words in a given plane, then the pointer
in the first 32 bytes of the chunk is =0.
2.2.2 Format for method 4
The DLTA chunk is modified slightly to have 16 long pointers at
the start. The first 8 are as before - pointers to the start of
the data for each of the bitplanes (up to a theoretical max of 8
planes). The next 8 are pointers to the start of the offset/numbers
data list. If there is only one list of offset/numbers for all
planes, then the pointer to that list is repeated in all positions
so the playback code need not even be aware of it. In fact, one
could get fancy and have some bitplanes share lists while others
have different lists, or no lists (the problems in these schemes
lie in the generation, not in the playback).
The best way to show the use of this format is in a sample playback
routine.
SetDLTAshort(bm,deltaword)
struct BitMap *bm;
WORD *deltaword;
{
int i;
LONG *deltadata;
WORD *ptr,*planeptr;
register int s,size,nw;
register WORD *data,*dest;
deltadata = (LONG *)deltaword;
nw = bm->BytesPerRow >>1;
for (i=0;i<bm->Depth;i++) {
planeptr = (WORD *)(bm->Planes[i]);
data = deltaword + deltadata[i];
ptr = deltaword + deltadata[i+8];
while (*ptr != 0xFFFF) {
dest = planeptr + *ptr++;
size = *ptr++;
if (size < 0) {
for (s=size;s<0;s++) {
*dest = *data;
dest += nw;
}
data++;
}
else {
for (s=0;s<size;s++) {
*dest = *data++;
dest += nw;
}
}
}
}
return(0);
}
The above routine is for short word vertical compression with
run length compression. The most efficient way to support
the various options is to replicate this routine and make
alterations for, say, long word or XOR. The variable nw
indicates the number of words to skip to go down the vertical
column. This one routine could easily handle horizontal
compression by simply setting nw=1. For ultimate playback
speed, the core, at least, of this routine should be coded in
assembly language.
2.2.2 Format for method 5
In this method the same 16 pointers are used as in option 4.
The first 8 are pointers to the data for up to 8 planes.
The second set of 8 are not used but were retained for several
reasons. First to be somewhat compatible with code for option
4 (although this has not proven to be of any benefit) and
second, to allow extending the format for more bitplanes (code
has been written for up to 12 planes).
Compression/decompression is performed on a plane-by-plane basis.
For each plane, compression can be handled by the skip.c code
(provided Public Domain by Jim Kent) and decompression can be
handled by unvscomp.asm (also provided Public Domain by Jim Kent).
Compression/decompression is performed on a plane-by-plane basis.
The following description of the method is taken directly from
Jim Kent's code with minor re-wording. Please refer to Jim's
code (skip.c and unvscomp.asm) for more details:
Each column of the bitplane is compressed separately.
A 320x200 bitplane would have 40 columns of 200 bytes each.
Each column starts with an op-count followed by a number
of ops. If the op-count is zero, that's ok, it just means
there's no change in this column from the last frame.
The ops are of three classes, and followed by a varying
amount of data depending on which class:
1. Skip ops - this is a byte with the hi bit clear that
says how many rows to move the "dest" pointer forward,
ie to skip. It is non-zero.
2. Uniq ops - this is a byte with the hi bit set. The hi
bit is masked down and the remainder is a count of the
number of bytes of data to copy literally. It's of
course followed by the data to copy.
3. Same ops - this is a 0 byte followed by a count byte,
followed by a byte value to repeat count times.
Do bear in mind that the data is compressed vertically rather
than horizontally, so to get to the next byte in the destination
we add the number of bytes per row instead of one!
-------------------------------------------------------------------------
Appendix for Anim7 Formats Wolfgang Hofer, 23.6.92
-------------------------------------------------------------------------
Anim method 7 is designed for maximum playback speed and acceptable
packing rates (packing usually not as good as method 5, but more
efficient than methodes 1 -- 4)
Method 7 is not in the IFF specification today
but supported by the Public Domain Programs AAP/AAC.
#.# Chunk Sequence:
Method 7 Anims should use the same Chunk Sequence as methods 1..5.
Alternativley the first frame may have a DLTA chunk instead
of the BODY chunk.
In that case the DLTA is the difference to a 'black frame'.
A player has to clear all bitplanes of the first bitmap to zero,
and then call his DLTA unpack routines for this frame.
FORM ANIM
. FORM ILBM first frame
. . BMHD normal type IFF data
. . ANHD optional animation header
chunk for timing of 1st frame.
. . CMAP
. . { BODY | full picture or
DLTA } difference to 'black frame'
. FORM ILBM frame 2
. . ANHD animation header chunk
. . DLTA delta mode data
. . [CMAP]
. FORM ILBM frame 3
. . ANHD
. . DLTA
. . [CMAP]
...
The initial FORM ILBM can contain all the normal ILBM chunks,
such as CRNG, etc. The BODY will normally be a standard
run-length-encoded data chunk (but may be any other legal
compression mode as indicated by the BMHD). If desired, an ANHD
chunk can appear here to provide timing data for the first
frame. If it is here, the operation field should be =0.
If the initial FORM ILBM uses a DLTA chunk, the ANHD chunk
must appear, and the operation field must be set to the
according anim method.
# Chunk Formats
#.# ANHD Chunk for method 7
The ANHD chunk consists of the following data structure:
UBYTE operation The compression method:
=7 short/long Vertical Delta mode
UBYTE mask unused
UWORD w,h unused
WORD x,y unused
ULONG abstime unused
ULONG reltime (timing for frame relative to time
previous frame was displayed - in
jiffies (1/60 sec))
UBYTE interleave = 0 (see ANHD description above)
UBYTE pad0 unused
ULONG bits 32 option bits used by methode=4 and 5.
methode 7 uses only bit #0
bit # set =0 set =1
===============================================
0 short data long data
UBYTE pad[16] unused
#.# DLTA Chunk
#.#.# Format for method 7
The DLTA Chunks of method7 consists of
- 8 pointers to opcode lists
- 8 pointers to data lists
- data lists (long/short)
- opcode lists (bytes)
In this method the DLTA Chunk begins with 16 pointers.
The first 8 longwords are pointers to the
opcode lists for up to 8 planes.
The second set of 8 longwords are pointers to the correspondig
data lists.
If there are less than 8 Planes all unused pointers are set to
zero.
Compression/decompression is performed on a plane-by-plane basis.
The following description of the method is similar to
Jim Kent's methode 5, except that data is stored in a seperated
datalist (long or short, depending on bit#0 of the ANHD bits)
and doesn't follow immediate after the opcode.
In methode 7 the bitplane is splitted into vertical columns.
Each column of the bitplane is compressed separately.
A 320x200 bitplane would have 20 columns of 200 short datas each.
(or 10 columns of 200 long datas)
Each column starts with an op-count followed by a number
of ops. If the op-count is zero, that's ok, it just means
there's no change in this column from the last frame.
The ops are of three classes. The ops refer to a varying
amount of data (to fetch from the corresponding datalist)
depending on which class:
1. Skip ops - this is a byte with the hi bit clear that
says how many rows to move the "dest" pointer forward,
ie to skip. It is non-zero.
Skip ops have no corresponding data-items in the datalist.
2. Uniq ops - this is a byte with the hi bit set. The hi
bit is masked down and the remainder is a count of the
number of data to copy literally from the datalist
to the "dest" pointer column. (Each data item to the
next destination row)
Data items may be long or short organized.
3. Same ops - this is a 0 byte followed by a count byte.
The count byte says how many rows of the current column
are to be set to the same data-item.
the data-item (long or short) is fetched from the
datalist.
Do bear in mind that the data is compressed vertically rather
than horizontally, so to get to the next address in the
destination we have to add the number of bytes per row
instead of 2 (or 4)!